using IQIGame.Onigao.Framework;
using IQIGame.Onigao.Game;
using System.Collections.Generic;
using UnityEngine;

namespace IQIGame.Onigao.GamePlay
{
    /// <summary>
    /// 逻辑相关处理
    /// </summary>
    public partial class LevelPlayEntityCtrl
    {

        public bool activeLogicUpdate { get; private set; }
        private float _checkTime = 0;

        public static Vector3 CharacterObbSize { get; } = new Vector3(0.1f, 1f, 0.1f);

        /// <summary>
        /// 当前触发的状态记录列表
        /// </summary>
        public DynParamEffectiveList dynParamEffectiveList { get; } = new DynParamEffectiveList();

        /// <summary>
        /// 当前所在的触发区域
        /// </summary>
        private Dictionary<BaseEntityDynamicParam, LevelPlayBaseEntity> _currentParamMapping = new();

        /// <summary>
        /// 更新数据的临时字段
        /// </summary>
        private Dictionary<BaseEntityDynamicParam, LevelPlayBaseEntity> _updateParmMapping = new();

        private void InitLogicInternal()
        {
            dynParamEffectiveList.onParamEffectAdded += OnParamEffectiveAdded;
            dynParamEffectiveList.onParamEffectRemoved += OnParamEffectiveRemoved;
            dynParamEffectiveList.onParamListChanged += OnParamEffectiveListChanged;
            MsgDispatcher.AddListener<LevelPlayBaseEntity, EntityParamSwitchState, int>(MsgEventType.Level_EntityStateChanged, OnTriggerEntityStateChanged);
        }

        private void DisposeLogic()
        {
            MsgDispatcher.RemoveListener<LevelPlayBaseEntity, EntityParamSwitchState, int>(MsgEventType.Level_EntityStateChanged, OnTriggerEntityStateChanged);
        }

        private void UpdateLogicInternal(float deltaTime)
        {
            //尝试去检测交互
            if (!activeLogicUpdate)
            {
                return;
            }

            _checkTime += deltaTime;
            if (_checkTime >= GameGlobalConst.EntityLogicInterval)
            {
                //_checkTime -= GameGlobalConst.EntityLogicInterval;
                _checkTime = 0;
                CheckEntityLogic();
            }
        }



        #region 触发状态检测和事件

        protected void CheckEntityLogic()
        {
            var character = GetMainCharacter();
            if (character == null)
            {
                return;
            }

            var characerUnityPos = character.GetUnityVec3Pos();

            var bvhEntitys = ListPool<LevelPlayBaseEntity>.Get();

            if (triggerRangeEntitys.Count > 0)
            {
                // 查询bvhtree 
                var characterBounds = BVHBounds2D.FromPosSize(characerUnityPos, CharacterObbSize);
                this.BVHRetrieveObjects(bvhEntitys, characterBounds);
            }


            if (bvhEntitys.Count == 0)
            {
                ListPool<LevelPlayBaseEntity>.Put(bvhEntitys);
                //清除当前的生效的效果
                dynParamEffectiveList.Clear();
                _currentParamMapping.Clear();
                return;
            }

            _updateParmMapping.Clear();

            foreach (var entity in bvhEntitys)
            {
                IReadOnlyDictionary<EntityDynamicParamType, BaseEntityDynamicParam> paramMap = null;
                var dynEntity = entity.GetDynLevelEntity();
                if (dynEntity != null)
                {
                    paramMap = dynEntity.levelEntityConfig.paramMap;
                }
                if (paramMap == null)
                {
                    continue;
                }

                BaseEntityDynamicParam paramValue = null;
                // 是否需要判断高度
                bool ignoreTriggerHeight = false;
                foreach (var kv in paramMap)
                {
                    var process = dynParamPrcoesses[(int)kv.Key];
                    if (process != null && process.isContainTriggerRect)
                    {
                        ignoreTriggerHeight = process.ignoreTriggerHeight;
                        paramValue = kv.Value;
                        break;
                    }
                }

                //创建obb对象并且检测
                EntityParamTriggerRect triggerRect = null;
                if (paramValue == null)
                {
                    continue;
                }
                if (!paramMap.TryGetValue(EntityDynamicParamType.TriggerRect, out var triggerRectParam))
                {
                    continue;
                }
                triggerRect = triggerRectParam as EntityParamTriggerRect;

                if (CheckInTriggerRect(entity, ignoreTriggerHeight))
                {
                    if (paramValue != null)
                    {
                        _updateParmMapping[paramValue] = entity;
                    }
                    _updateParmMapping[triggerRect] = entity;
                }
            }

            //回收List
            ListPool<LevelPlayBaseEntity>.Put(bvhEntitys);

            //交换索引
            CollectionsExtension.Swap(ref _currentParamMapping, ref _updateParmMapping);

            // 差异更新数据，这里不转为IReadonlyDictionary主要是考虑interface的GetEnumerator接口会有GC
            dynParamEffectiveList.UpdateParamEffectives(_updateParmMapping, _currentParamMapping);

        }

        public bool CheckInTriggerRect(LevelPlayBaseEntity entity, bool ignoreTriggerHeight)
        {
            var character = GetMainCharacter();
            if (character == null)
            {
                return false;
            }
            var characerUnityPos = character.GetUnityVec3Pos();
            var dynEntity = entity.GetDynLevelEntity();
            var paramMap = dynEntity.levelEntityConfig.paramMap;
            if (paramMap == null)
            {
                return false;
            }
            if (!paramMap.TryGetValue(EntityDynamicParamType.TriggerRect, out var triggerRectParam))
            {
                return false;
            }
            var triggerRect = triggerRectParam as EntityParamTriggerRect;
            var unityPos = entity.GetUnityVec3Pos();
            if (!ignoreTriggerHeight)
            {
                // 判断高度差，是否在允许范围,如果是0表示无限大
                if (triggerRect.halfHeight > 0 && (Mathf.Abs(unityPos.y - characerUnityPos.y) * 100) > triggerRect.halfHeight)
                {
                    return false;
                }
            }
            //创建当前实体OBB
            var offset = GameMathUtil.GetRectOffset(triggerRect.rect);
            float rotationY = 0;
            if (triggerRect.isRotatable)
            {
                var euler = GameMathUtil.IntEulerToVector3(entity.dirEuler);
                rotationY = euler.y;
                offset = Quaternion.Euler(euler) * offset;
            }
            var size = LevelMathUtil.Rect2OBBSize(triggerRect.rect);
            var entityOBB = new OBBRect(unityPos + offset, size, rotationY);

            //创建主角OBB
            var characterOBB = new OBBRect(characerUnityPos, CharacterObbSize, 0);
            //OBB碰撞检测
            return characterOBB.IsIntersecting(entityOBB);
        }

        /// <summary>
        /// 单个添加通知
        /// </summary>
        /// <param name="paramValue"></param>
        /// <param name="entity"></param>
        private void OnParamEffectiveAdded(BaseEntityDynamicParam paramValue, LevelPlayBaseEntity entity)
        {
            var process = dynParamPrcoesses[(int)paramValue.type];
            if (process != null)
            {
                process.OnOneParamEffectiveAdded(paramValue, entity);
            }
        }

        /// <summary>
        /// 单个移除通知
        /// </summary>
        /// <param name="paramValue"></param>
        /// <param name="entity"></param>
        private void OnParamEffectiveRemoved(BaseEntityDynamicParam paramValue, LevelPlayBaseEntity entity)
        {
            var process = dynParamPrcoesses[(int)paramValue.type];
            if (process != null)
            {
                process.OnOneParamEffectiveRemoved(paramValue, entity);
            }
        }

        /// <summary>
        /// 类型中有变化通知
        /// </summary>
        /// <param name="paramType"></param>
        /// <param name="paramValueList"></param>
        /// <param name="entityList"></param>
        private void OnParamEffectiveListChanged(EntityDynamicParamType paramType, IReadOnlyList<BaseEntityDynamicParam> paramValueList, IReadOnlyList<LevelPlayBaseEntity> entityList)
        {
            var process = dynParamPrcoesses[(int)paramType];
            if (process != null)
            {
                process.OnListParamEffectiveChanged(paramType, paramValueList, entityList);
            }
        }

        #endregion

        #region 其他特殊逻辑

        private void OnTriggerEntityStateChanged(LevelPlayBaseEntity entity, EntityParamSwitchState switchState, int stateIndex)
        {
            if (!_currentParamMapping.ContainsKey(switchState))
            {
                return;
            }

            CLevelLogicModule.NetCore.CS_TriggerInEntityState(entity.id, stateIndex);
        }
        #endregion

    }
}
